﻿using B.T.BasicData.Domain.RBAC;
using B.T.BasicData.ErrorCode;
using B.T.BasicData.Infraeturcture;
using B.T.BasicData.Read.Api.Common;
using B.T.BasicData.Read.Api.Common.ICommon;
using B.T.BasicData.Read.Api.DTOs;
using B.T.BasicData.Read.Api.RBACServices.IServices;
using MD5Hash;
using Microsoft.IdentityModel.Tokens;
using System.Data;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;

namespace B.T.BasicData.Read.Api.RBACServices.Services
{
    /// <summary>
    /// 登录服务实现
    /// </summary>
    public class LoginServices : ILoginServices
    {
        private readonly ILogger<LoginServices> logger;
        private readonly IBaseRepository<Userinfo> userRepository;
        private readonly IBaseRepository<User_Role> userRoleRepository;
        private readonly IBaseRepository<RolesInfo> roleRepository;
        private readonly IBaseRepository<Role_Permission> rolePermissionRepository;
        private readonly IBaseRepository<Permissions> permissionRepository;
        private readonly IConfiguration configuration;
        private readonly IIdentivyService identivyService;

        public LoginServices(
            ILogger<LoginServices> logger,
            IBaseRepository<Userinfo> userRepository,
            IBaseRepository<User_Role> userRoleRepository,
            IBaseRepository<RolesInfo> roleRepository,
            IBaseRepository<Role_Permission> rolePermissionRepository,
            IBaseRepository<Permissions> permissionRepository,IConfiguration _configuration,IIdentivyService identivyService)
            
        {
            this.logger = logger;
            this.userRepository = userRepository;
            this.userRoleRepository = userRoleRepository;
            this.roleRepository = roleRepository;
            this.rolePermissionRepository = rolePermissionRepository;
            this.permissionRepository = permissionRepository;
            configuration = _configuration;
            this.identivyService = identivyService;
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="loginDto">登录信息</param>
        /// <returns>登录结果</returns>
        public async Task<ApiResult<LoginResultDto>> Login(LoginDto loginDto)
        {
            logger.LogInformation($"用户登录尝试: {loginDto.UserName}");
            
            var result = new ApiResult<LoginResultDto>();

            try
            {
                // 参数验证
                if (string.IsNullOrEmpty(loginDto.UserName) || string.IsNullOrEmpty(loginDto.Password))
                {
                    result.msg = "用户名或密码不能为空";
                    return result;
                }

                // 对密码进行MD5加密
                var encryptedPassword = loginDto.Password.GetMD5();

                // 查询用户信息
                var user = userRepository.Getlist().FirstOrDefault(x => x.UserName == loginDto.UserName && x.Password == encryptedPassword && !x.IsDeleted);

                if (user == null)
                {
                    result.msg = "用户名或密码错误";
                    logger.LogWarning($"登录失败: 用户名 {loginDto.UserName} 验证失败");
                    return result;
                }

                if (!user.status)
                {
                    result.msg = "用户已被禁用";
                    logger.LogWarning($"登录失败: 用户 {loginDto.UserName} 已被禁用");
                    return result;
                }

                // 查询用户角色
                var userRoles = userRoleRepository.Getlist().Where(x => x.UserId == user.UserId && !x.IsDele).ToList();

                var roleIds = userRoles.Select(x => x.RolesId).ToList();
                var roles = roleRepository.Getlist().Where(x => roleIds.Contains(x.RolesId) && !x.IsDeleted).ToList();

                // 查询角色权限
                var rolePermissions = rolePermissionRepository.Getlist().Where(x => roleIds.Contains(x.RolesId) && !x.IsDele).ToList();

                var permissionIds = rolePermissions.Select(x => x.PermissionsId).Distinct().ToList();
                var permissions = permissionRepository.Getlist().Where(x => permissionIds.Contains(x.PermissionsId) && !x.IsDeleted).ToList();


                // 构建返回结果
                var loginResult = new LoginResultDto
                {
                    UserId = user.UserId,
                    UserName = user.UserName,
                    Status = user.status,
                    Token= CreateTokenString(user.UserId, user.UserName),
                    Roles = roles.Select(r => new RoleInfo
                    {
                        RoleId = r.RolesId,
                        RoleName = r.RoleName
                    }).ToList(),
                    Permissions = permissions.Select(p => new PermissionInfo
                    {
                        PermissionId = p.PermissionsId,
                        PermissionName = p.PermissionName,
                        Component = p.Component
                    }).ToList()
                };

                result.success(loginResult);
                result.msg = "登录成功";
                
                logger.LogInformation($"用户 {loginDto.UserName} 登录成功，角色数量: {loginResult.Roles.Count}，权限数量: {loginResult.Permissions.Count}");
                
                return result;
            }
            catch (Exception ex)
            {
                logger.LogError($"登录过程中发生异常: {ex.Message}");
                result.msg = "登录过程中发生异常";
                return result;
            }
        }

        /// <summary>
        /// 对明文密码进行MD5加密
        /// </summary>
        /// <param name="password">明文密码</param>
        /// <returns>加密后的字符串</returns>
        private string Md5Encrypt(string password)
        {
            using (var md5 = MD5.Create())
            {
                var bytes = Encoding.UTF8.GetBytes(password);
                var hash = md5.ComputeHash(bytes);
                return BitConverter.ToString(hash).Replace("-", "").ToLower();
            }
        }


        /// <summary>
        /// 生成 JWT Token（令牌）
        /// </summary>
        /// <returns></returns>
        private string CreateTokenString(long ? UserId, string ? UserName)
        {
            //读取配置文件
            var jwtSettings = configuration.GetSection("JWtSettings").Get<JWtSettings>();

            //私钥
            var secretByte = Encoding.UTF8.GetBytes(jwtSettings.SigningKey);
            // 非对称加密
            var signingKey = new SymmetricSecurityKey(secretByte);
            // 使用256 生成数字签名
            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

            //Claims  荷载  指用户信息 用户名  用户Id 角色Id  
            var claims = new[]
            {
                new Claim(System.Security.Claims.ClaimTypes.NameIdentifier, Convert.ToString(UserId)),
                new Claim("NickName", UserName),
            };

            // 生成Token
            var token = new JwtSecurityToken(
                issuer: jwtSettings.Issuer,
                audience: jwtSettings.Audience,
                expires: DateTime.Now.AddMinutes(jwtSettings.AccessTokenExpirationMinutes), // 两分钟之后过期  (AddHours(小时)、AddMinutes(分钟)、AddDays(按天)、AddMonths(按月))
                signingCredentials: signingCredentials,
                claims: claims
            );
            // 生成token 字符串
            var strToken = new JwtSecurityTokenHandler().WriteToken(token);
            return strToken;
        }
    }
}
